home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 5 / Apprentice-Release5.iso / Source Code / C / Applications / Moscow ML 1.31 / source code / mosml / src / compiler / Compiler.sml < prev    next >
Encoding:
Text File  |  1996-07-03  |  11.4 KB  |  422 lines  |  [TEXT/R*ch]

  1. (* Compiler.sml *)
  2.  
  3. open List Obj BasicIO Nonstdio Fnlib Mixture Const Globals Location Units;
  4. open Types Smlperv Asynt Parser Ovlres Infixres Elab Sigmtch;
  5. open Tr_env Front Back Pr_zam Emit_phr;
  6.  
  7. (* Lexer of stream *)
  8.  
  9. fun createLexerStream (is : BasicIO.instream) =
  10.   Lexing.createLexer (fn buff => fn n => Nonstdio.buff_input is buff 0 n)
  11. ;
  12.  
  13. (* Parsing functions *)
  14.  
  15. fun parsePhrase parsingFun lexingFun lexbuf =
  16.   let fun skip() =
  17.     (case lexingFun lexbuf of
  18.         EOF => ()
  19.       | SEMICOLON => ()
  20.       | _ => skip())
  21.     handle LexicalError(_,_,_) =>
  22.       skip()
  23.   in
  24.     parsingFun lexingFun lexbuf
  25.     handle
  26.         Parsing.ParseError f =>
  27.            let val pos1 = Lexing.getLexemeStart lexbuf
  28.                val pos2 = Lexing.getLexemeEnd lexbuf
  29.            in
  30.              Lexer.resetLexerState();
  31.              if f (Obj.repr EOF) orelse
  32.                 f (Obj.repr SEMICOLON)
  33.              then () else skip();
  34.              msgIBlock 0;
  35.              errLocation (Loc(pos1, pos2));
  36.              errPrompt "Syntax error.";
  37.              msgEOL();
  38.              msgEBlock();
  39.              raise Toplevel
  40.            end
  41.        | LexicalError(msg, pos1, pos2) =>
  42.            (msgIBlock 0;
  43.             if pos1 >= 0 andalso pos2 >= 0 then
  44.               errLocation (Loc(pos1, pos2))
  45.             else ();
  46.             errPrompt "Lexical error: "; msgString msg;
  47.             msgString "."; msgEOL();
  48.             msgEBlock();
  49.             skip();
  50.             raise Toplevel)
  51.        | Toplevel =>
  52.            (skip ();
  53.             raise Toplevel)
  54.   end
  55. ;
  56.  
  57. fun parsePhraseAndClear parsingFun lexingFun lexbuf =
  58.   let val phr =
  59.     parsePhrase parsingFun lexingFun lexbuf
  60.     handle x => (Lexer.resetLexerState(); Parsing.clearParser(); raise x)
  61.   in
  62.     Lexer.resetLexerState();
  63.     Parsing.clearParser();
  64.     phr
  65.   end;
  66.  
  67. val parseToplevelPhrase =
  68.   parsePhraseAndClear Parser.ToplevelPhrase Lexer.Token
  69. ;
  70.  
  71. val parseBodyPhrase =
  72.   parsePhraseAndClear Parser.BodyPhrase Lexer.Token
  73. ;
  74.  
  75. val parseToplevelSpecPhrase =
  76.   parsePhraseAndClear Parser.SpecPhrase Lexer.Token
  77. ;
  78.  
  79. fun isInTable key tbl =
  80.   (Hasht.find tbl key; true)
  81.   handle Subscript => false
  82. ;
  83.  
  84. fun filter p xs =
  85.   rev(foldL (fn x => fn acc => if p x then x::acc else acc) [] xs)
  86. ;
  87.  
  88. fun filterExcRenList excRenList cBas =
  89.   filter (fn ({qual, id}, _) => isInTable id cBas) excRenList
  90. ;
  91.  
  92. fun filterValRenList valRenList cBas =
  93.   filter (fn (id, stamp) => isInTable id cBas) valRenList
  94. ;
  95.  
  96. fun cleanEnvAcc [] acc = acc
  97.   | cleanEnvAcc ((k, v) :: rest) acc =
  98.       if exists (fn (k', _) => k = k') acc then
  99.         cleanEnvAcc rest acc
  100.       else
  101.         cleanEnvAcc rest ((k, v) :: acc)
  102. ;
  103.  
  104. fun cleanEnv env =
  105.   cleanEnvAcc (foldEnv (fn a => fn x => fn acc => (a,x)::acc) [] env) []
  106. ;
  107.  
  108. (* Reporting the results of compiling a phrase *)
  109.  
  110. val verbose = ref false;
  111.  
  112. fun reportFixityResult (id, status) =
  113. (
  114.   (case status of
  115.        NONFIXst =>
  116.          msgString "nonfix "
  117.      | INFIXst i =>
  118.          (msgString "infix ";
  119.           msgInt i; msgString " ")
  120.      | INFIXRst i =>
  121.          (msgString "infixr ";
  122.           msgInt i; msgString " "));
  123.   msgString id
  124. );
  125.  
  126. fun reportEquOfType equ =
  127.   msgString
  128.     (case equ of
  129.          FALSEequ => ""
  130.        | TRUEequ => "eq"
  131.        | REFequ => "prim_EQ")
  132. ;
  133.  
  134. fun reportLhsOfTypeResult (tyname : TyName) =
  135.   let val vs = newTypeVars (#tnArity (!(#info tyname)))
  136.       val lhs = type_con (map TypeOfTypeVar vs) tyname
  137.   in printType lhs end
  138. ;
  139.  
  140. fun reportTypeResult (tyname : TyName) =
  141.   let val {qualid, info} = tyname
  142.       val {tnEqu, tnStr, ...} = !info
  143.   in
  144.     case tnStr of
  145.         NILts =>
  146.           (reportEquOfType tnEqu;
  147.            msgString "type ";
  148.            reportLhsOfTypeResult tyname)
  149.       | TYPEts(vs, tau) =>
  150.           let val lhs = type_con (map TypeOfTypeVar vs) tyname in
  151.             msgString "type ";
  152.             resetTypePrinter();
  153.             collectExplicitVars lhs;
  154.             collectExplicitVars tau;
  155.             printNextType lhs; msgString " ="; msgBreak(1, 2);
  156.             printNextType tau;
  157.             resetTypePrinter()
  158.           end
  159.       | DATATYPEts dt =>
  160.           let val uname = #qual qualid
  161.               val sig = if uname = currentUnitName()
  162.                         then (!currentSig)
  163.                         else findSig Location.nilLocation uname
  164.               val CE = findConstructors sig dt
  165.           in
  166.             if null CE then
  167.               (msgString "abstype ";
  168.                reportLhsOfTypeResult tyname)
  169.             else
  170.               (msgString "datatype ";
  171.                reportLhsOfTypeResult tyname)
  172.           end
  173.       | REAts _ =>
  174.              fatalError "reportTypeResult"
  175.   end
  176. ;
  177.  
  178. fun lookup_new_cBas cBas id =
  179.   (lookupEnv cBas id : ConStatus)
  180.   handle Subscript => fatalError "lookup_new_cBas"
  181. ;
  182.  
  183. fun report_comp_results iBas cBas static_VE static_TE =
  184. (
  185.   app (fn x =>
  186.          (msgIBlock 0; reportFixityResult x; msgEOL(); msgEBlock()))
  187.       (cleanEnv iBas);
  188.   app (fn (id, tn) =>
  189.          (msgIBlock 0; reportTypeResult tn; msgEOL(); msgEBlock()))
  190.       (cleanEnv static_TE);
  191.   app
  192.     (fn (id, sch) =>
  193.        let val status = lookup_new_cBas cBas id in
  194.          msgIBlock 0;
  195.          msgCBlock 0;
  196.          msgString
  197.            (case #info status of
  198.                VARname  _ => "val "
  199.              | PRIMname _ => "val "
  200.              | CONname  _ => "con "
  201.              | EXNname  _ => "exn "
  202.              | REFname    => "con ");
  203.          msgString id;
  204.          msgString " :"; msgBreak(1, 2); printScheme sch;
  205.          msgEBlock();
  206.          msgEOL();
  207.          msgEBlock()
  208.        end)
  209.     (cleanEnv static_VE);
  210.     msgFlush()
  211. );
  212.  
  213. (* To write the signature of the unit currently compiled *)
  214. (* The same value has to be written twice, because it's unclear *)
  215. (* how to `open` a file in "read/write" mode in a Caml Light program. *)
  216.  
  217. fun writeCompiledSignature filename_ui =
  218.   let val sigStamp = ref dummySigStamp
  219.       val sigLen = ref 0
  220.   in
  221.     let val os = open_out_bin filename_ui in
  222.       (output_value os (!currentSig);
  223.        sigLen := pos_out os;
  224.        close_out os)
  225.       handle x =>
  226.         (close_out os;
  227.          remove_file filename_ui;
  228.          raise x)
  229.     end;
  230.     let val is = open_in_bin filename_ui in
  231.       let val sigImage = input(is, !sigLen) in
  232.         if size sigImage < !sigLen then raise Size else ();
  233.         close_in is;
  234.         remove_file filename_ui;
  235.         sigStamp := Crc.crcOfString sigImage
  236.       end
  237.       handle x =>
  238.         (close_in is;
  239.          remove_file filename_ui;
  240.          raise x)
  241.     end;
  242.     let val os = open_out_bin filename_ui in
  243.       (output(os, !sigStamp);
  244.        output_value os (!currentSig);
  245.        close_out os)
  246.       handle x =>
  247.         (close_out os;
  248.          remove_file filename_ui;
  249.          raise x)
  250.     end;
  251.     !sigStamp
  252.   end;
  253.  
  254. (* Compiling a signature *)
  255.  
  256. fun compileSpecPhrase spec =
  257.   let val (iBas, cBas) = resolveToplevelSpec spec
  258.       val (VE, TE) = elabToplevelSpec spec
  259.   in
  260.     updateCurrentInfixBasis iBas;
  261.     extendCurrentConBasis cBas;
  262.     extendCurrentStaticTE TE;
  263.     updateCurrentStaticVE VE;
  264.     if !verbose then
  265.       (report_comp_results iBas cBas VE TE;
  266.        msgFlush())
  267.     else ()
  268.   end
  269. ;
  270.  
  271. fun compileSignature uname filename =
  272.   let
  273.     val source_name = filename ^ ".sig"
  274.     val target_name = filename ^ ".ui"
  275.     (* val () = (msgIBlock 0;
  276.                  msgString "[compiling file \""; msgString source_name;
  277.                  msgString "\"]"; msgEOL(); msgEBlock();) *)
  278.     val () = startCompilingUnit uname
  279.     val () = initInitialEnvironments()
  280.     val is = open_in_bin source_name
  281.     val () = remove_file target_name;
  282.     val lexbuf = createLexerStream is
  283.   in
  284.     input_name := source_name;
  285.     input_stream := is;
  286.     input_lexbuf := lexbuf;
  287.     (while true do
  288.        let val (phrase, isLast) = parseToplevelSpecPhrase lexbuf in
  289.          compileSpecPhrase phrase;
  290.          if isLast then raise EndOfFile else ()
  291.        end)
  292.     handle
  293.       EndOfFile =>
  294.         let val (_, _) = rectifySignature()
  295.             val sigStamp = writeCompiledSignature target_name
  296.         in close_in is end
  297.     | x =>
  298.         (close_in is;
  299.          raise x)
  300.   end
  301. ;
  302.  
  303. (* Compiling an implementation *)
  304.  
  305. (* This is written in tail-recursive form to ensure *)
  306. (* that the intermediate results will be discarded. *)
  307.  
  308. fun updateCurrentCompState ((iBas, cBas, VE, TE), RE) =
  309. (
  310.   updateCurrentInfixBasis iBas;
  311.   updateCurrentConBasis cBas;
  312.   updateCurrentStaticTE TE;
  313.   updateCurrentStaticVE VE;
  314.   updateCurrentRenEnv RE;
  315.   if !verbose then
  316.     (report_comp_results iBas cBas VE TE;
  317.      msgFlush())
  318.   else ()
  319. );
  320.  
  321. fun compLamPhrase os state (RE, lams) =
  322. (
  323.   app
  324.     (fn (is_pure, lam) =>
  325.        ((* msgIBlock 0; printLam lam; msgEOL(); msgEBlock(); *)
  326.        emit_phrase os
  327.          let val zam = compileLambda is_pure lam in
  328.            (* printZamPhrase zam; msgFlush(); *)
  329.            zam
  330.          end))
  331.     lams;
  332.     updateCurrentCompState (state, RE)
  333. );
  334.  
  335. fun compResolvedDecPhrase os (iBas, cBas, dec) =
  336.   let val (VE, TE) = elabToplevelDec dec in
  337.     resolveOvlDec dec;
  338.     compLamPhrase os (iBas, cBas, VE, TE) (translateToplevelDec dec)
  339.   end
  340. ;
  341.  
  342. fun compileImplPhrase os dec =
  343.   compResolvedDecPhrase os (resolveToplevelDec dec)
  344. ;
  345.  
  346. fun compileImpl uname filename specSig_opt =
  347.   let
  348.     val filename_sml = filename ^ ".sml"
  349.     val filename_ui  = filename ^ ".ui"
  350.     val filename_uo  = filename ^ ".uo"
  351.     (* val () = (msgIBlock 0;
  352.                  msgString "[compiling file \""; msgString filename_sml;
  353.                  msgString "\"]"; msgEOL(); msgEBlock()) *)
  354.     val () = startCompilingUnit uname
  355.     val () = initInitialEnvironments()
  356.     val is = open_in_bin filename_sml
  357.     val os = open_out_bin filename_uo
  358.     val lexbuf = createLexerStream is
  359.   in
  360.     input_name := filename_sml;
  361.     input_stream := is;
  362.     input_lexbuf := lexbuf;
  363.     (
  364.       start_emit_phrase os;
  365.       (while true do
  366.          let val (phrase, isLast) = parseBodyPhrase lexbuf in
  367.            compileImplPhrase os phrase;
  368.            if isLast then raise EndOfFile else ()
  369.          end)
  370.       handle EndOfFile =>
  371.         let val (excRenList, valRenList) = rectifySignature() in
  372.           (case specSig_opt of
  373.                NONE =>
  374.                  let val sigStamp = writeCompiledSignature filename_ui in
  375.                    end_emit_phrase
  376.                      excRenList valRenList
  377.                      sigStamp (#uMentions (!currentSig))
  378.                      os
  379.                  end
  380.              | SOME specSig =>
  381.                  let val {uConBasis, uStamp, ...} = specSig in
  382.                    matchSignature os (!currentSig) specSig;
  383.                    end_emit_phrase
  384.                      (filterExcRenList excRenList uConBasis)
  385.                      (filterValRenList valRenList uConBasis)
  386.                      (getOption (!uStamp)) (#uMentions (!currentSig))
  387.                      os
  388.                  end);
  389.           close_in is;
  390.           close_out os
  391.         end
  392.     )
  393.     handle x =>
  394.       (close_in is;
  395.        close_out os;
  396.        remove_file filename_uo;
  397.        raise x)
  398.   end
  399. ;
  400.  
  401. fun compileUnitBody uname filename =
  402.   let val filename_sig = filename ^ ".sig"
  403.       val filename_ui  = filename ^ ".ui"
  404.   in
  405.     if file_exists filename_sig then
  406.       (hasSpecifiedSignature := true;
  407.        if not(file_exists filename_ui) then
  408.          (msgIBlock 0;
  409.           errPrompt "File "; msgString filename_sig;
  410.           msgString " must be compiled before ";
  411.           msgString filename; msgString ".sml"; msgEOL();
  412.           msgEBlock();
  413.           raise Toplevel)
  414.        else ();
  415.        compileImpl uname filename (SOME (readSig uname)))
  416.     else
  417.       (hasSpecifiedSignature := false;
  418.        remove_file filename_ui;
  419.        compileImpl uname filename NONE)
  420.   end
  421. ;
  422.